// // Copyright (c) 2009 All Right Reserved // // vl // // 2009-01-01 // Contains ... using System; using System.Collections.Generic; using System.Diagnostics.Contracts; using System.Globalization; using System.Linq; using System.Text; using JetBrains.Annotations; namespace LargoCommon.Music { /// /// Harmonic Motive. /// [Serializable] public sealed class HarmonicMotive { #region Fields #endregion #region Constructors /// /// Initializes a new instance of the class. /// /// The given header. /// The harmonic motive number. public HarmonicMotive(MusicalHeader givenHeader, int harmonicMotiveNumber) : this() { this.HarmonicStream = new HarmonicStream(givenHeader); this.Shortcut = harmonicMotiveNumber.ToString(); this.Name = string.Format(CultureInfo.InvariantCulture, "H{0} from {1}", harmonicMotiveNumber, givenHeader.Name); this.Number = harmonicMotiveNumber; } /// /// Initializes a new instance of the class. /// public HarmonicMotive() { this.RhythmicBehavior = new RhythmicBehavior(); this.HarmonicBehavior = new HarmonicBehavior(); } #endregion #region Properties /// /// Gets or sets the full name. /// /// /// The full name. /// [UsedImplicitly] public string Name { get; set; } //// CA1044 (FxCop) /// /// Gets or sets the number. /// /// Property description. public int Number { get; set; } /// /// Gets or sets Harmonic Motive Bars. /// public HarmonicStream HarmonicStream { get; set; } /// /// Gets the outline of bars. /// /// Property description. [UsedImplicitly] public string OutlineOfBars { get { if (this.Length == 0) { return string.Empty; } var outline = new StringBuilder(); foreach (var s in this.HarmonicStream.HarmonicBars) { outline.Append(s.SimpleStructuralOutline); outline.Append(" | "); } return outline.ToString(); } } /// /// Gets the length. /// /// Property description. public int Length { get { if (this.HarmonicStream?.HarmonicBars == null) { return 0; } return this.HarmonicStream.HarmonicBars.Count; } } /// /// Gets or sets the harmonic behavior. /// /// /// The harmonic behavior. /// public HarmonicBehavior HarmonicBehavior { get; set; } /// /// Gets or sets the rhythmic behavior. /// /// /// The rhythmic behavior. /// public RhythmicBehavior RhythmicBehavior { get; set; } /// /// Gets or sets the name. /// /// /// Property description. /// public string Shortcut { get; set; } #endregion #region Private Properties /// Gets inner continuity. /// Property description. private float MeanContinuity { get { if (this.Length == 0) { return 0; } var total = (from HarmonicBar s in this.HarmonicStream.HarmonicBars select s.HarmonicBehavior.Continuity).Sum(); var f = total / this.Length; if (f != null) { var meanContinuity = (float)f; return meanContinuity; } return 0; } } /// Gets inner impulse. /// Property description. private float MeanImpulse { get { if (this.Length == 0) { return 0; } var total = (from HarmonicBar s in this.HarmonicStream.HarmonicBars select s.HarmonicBehavior.Impulse).Sum(); var f = total / this.Length; if (f != null) { var meanImpulse = (float)f; return meanImpulse; } return 0; } } /// Gets inner measure of dissonance. /// Property description. private float MeanConsonance { get { if (this.Length == 0) { return 0; } var total = (from HarmonicBar s in this.HarmonicStream.HarmonicBars select s.HarmonicBehavior.Consonance).Sum(); var meanConsonance = total / this.Length; return meanConsonance; } } /// /// Gets the mean rhythmic mobility. /// private float MeanRhythmicMobility { get { if (this.Length == 0) { return 0; } var total = (from HarmonicBar s in this.HarmonicStream.HarmonicBars select s.RhythmicBehavior.Mobility).Sum(); var meanValue = total / this.Length; return meanValue; } } /// /// Gets the mean rhythmic tension. /// private float MeanRhythmicTension { get { if (this.Length == 0) { return 0; } var total = (from HarmonicBar s in this.HarmonicStream.HarmonicBars select s.RhythmicBehavior.Tension).Sum(); var meanValue = total / this.Length; return meanValue; } } #endregion #region Public static methods /// /// Gets the new harmonic motive. /// /// The given header. /// The harmonic motive number. /// /// Returns value. /// public static HarmonicMotive GetNewHarmonicMotive(MusicalHeader givenHeader, int harmonicMotiveNumber) { //// var shortcut = ("0000" + harmonicMotiveNumber.ToString(CultureInfo.CurrentCulture)).Right(4); var harMotive = new HarmonicMotive(givenHeader, harmonicMotiveNumber); return harMotive; } /// /// Returns value of characteristic planned for given musical bar. /// /// Number of musical bar. /// The system. /// /// Returns value. /// /// No harmonic motive bar! public HarmonicBar HarmonicBarWithNumber(int barNumber, MusicalSystem system) { var listBars = this.HarmonicStream.HarmonicBars; //// (List)this.HarmonicBars; var barCount = listBars.Count; switch (barCount) { case 1: return listBars.First(); case 0: throw new ArgumentException("No harmonic motive bar!"); } int barnum; //// int lastBarNum = (from tmb in listBars select tmb.BarNumber).Max(); checked { barnum = ((barNumber - 1) % barCount) + 1; //// % lastBarNum } var selectedBar = from trb in listBars where (trb.BarNumber == barnum) select trb; //// var system = this.Core.Header.System; var harmonicBar = selectedBar.FirstOrDefault() ?? HarmonicBar.EmptyBar(system.HarmonicOrder, system.RhythmicOrder); return harmonicBar; } #endregion #region Public methods /// /// Adds the bar. /// /// The harmonic motive bar. public void AddBar(HarmonicBar bar) { Contract.Requires(bar != null); bar.Recompute(); ((List)this.HarmonicStream.HarmonicBars).Add(bar); } /// /// Returns a that represents this instance. /// /// /// A that represents this instance. /// [UsedImplicitly] public override string ToString() { return this.Name; } /// /// Re-computes this instance. /// public void Recompute() { this.HarmonicBehavior.Continuity = this.MeanContinuity; this.HarmonicBehavior.Impulse = this.MeanImpulse; this.HarmonicBehavior.Consonance = this.MeanConsonance; this.RhythmicBehavior.Mobility = this.MeanRhythmicMobility; this.RhythmicBehavior.Tension = this.MeanRhythmicTension; } #endregion } }